package be.dch.objectprops.impl;

import java.io.ObjectStreamClass;
import java.lang.reflect.Method;
import java.security.InvalidParameterException;

import org.apache.log4j.Logger;

import be.dch.exceptions.InstantiatingException;

public class ObjectStreamClassInstantiator {
    private static final Logger LOG = Logger.getLogger(ObjectStreamClassInstantiator.class);
    private static Method newInstanceMethod;
    private final ObjectStreamClass objStreamClass;

    private static void initialize() throws Exception {
	if (ObjectStreamClassInstantiator.newInstanceMethod != null) {
	    return;
	}
	try {
	    ObjectStreamClassInstantiator.newInstanceMethod = ObjectStreamClass.class.getDeclaredMethod("newInstance", new Class[0]);
	    ObjectStreamClassInstantiator.newInstanceMethod.setAccessible(true);

	} catch (final RuntimeException e) {
	    ObjectStreamClassInstantiator.LOG.error(e);
	    throw new InstantiatingException(e);
	} catch (final NoSuchMethodException e) {
	    ObjectStreamClassInstantiator.LOG.error(e);
	    throw new InstantiatingException(e);
	}
    }

    public ObjectStreamClassInstantiator(final Class<?> type) throws Exception {
	ObjectStreamClassInstantiator.initialize();
	this.objStreamClass = ObjectStreamClass.lookup(type);
	if (this.objStreamClass == null) {
	    throw new InvalidParameterException("Object is not serializable!");
	}
    }

    public Object newInstance() throws Exception {
	try {
	    return ObjectStreamClassInstantiator.newInstanceMethod.invoke(this.objStreamClass, new Object[0]);
	} catch (final Exception e) {
	    throw new InstantiatingException(e);
	}
    }
}